#include "GameObject.h"
#include "Player.h"
#include "BaseEntity.h"
#include "Model.h"
#include "Camera.h"
#include "GlobalDefines.h"
#include "DXConsole.h"
#include "Projectile3D.h"
#include "MessageHandler.h"
#include <math.h>
#include <stdio.h>

#define MOVE_RATE 10.0f

D3DCOLOR fontRedColor = D3DCOLOR_XRGB(255,0,0); 
D3DCOLOR fontGreenColor = D3DCOLOR_XRGB(0,255,0);
D3DCOLOR fontBlueColor = D3DCOLOR_XRGB(0,0,255);

Player::Player(int id):BaseEntity(id), 
					   m_release(false), 
					   m_pBall(false),
					   m_expand(false),
					   m_bscale(20.0f),
					   m_energy(100)
{
	m_size = .1;

	m_PlayerState = new StateMachine<Player>(this);

	m_PlayerState->SetCurrentState(PlayerIdleState::Instance());

	DSBuffer = dxAmgr.LoadWaveToSoundBuffer("punch2.wav");
	DSBuffer2 = dxAmgr.LoadWaveToSoundBuffer("DOOM58.WAV");
	DSBuffer3 = dxAmgr.LoadWaveToSoundBuffer("explosion2.wav");
	DSBuffer4 = dxAmgr.LoadWaveToSoundBuffer("bigboom.wav");
}

Player::~Player()
{
	if(m_Model != NULL)
	{
		delete m_Model;
		m_Model = NULL;
	}

	releaseSounds();
}

void Player::update(float a_dt)
{
	static char number[32];
	static char energy[32];

	m_dt=a_dt;

	m_camera->SetCamera(m_position.x,
						m_position.y,
						m_position.z,
						m_direction.x,
						m_direction.y, 
						m_direction.z,
						m_upDir.x,
						m_upDir.y, 
						m_upDir.z);

	_itoa((getHP()), number, 10);
	
	m_DXNOVA.DXOut(number,410,97,100,100);

	m_DXNOVA2.DXOut("Health:",410,0,100,100);

	chargeEnergy();

	_itoa(m_energy, energy, 10);

	m_DXNOVA3.DXOut(energy,445,100,100,100);

	m_DXNOVA4.DXOut("Energy:",445,0,100,100);

	m_camera->UpdateCamera();
}

bool Player::HandleMessage(const Telegram& msg)
{
	bool ihandled;
	if(msg.Msg==MSG_COLLIDE)
	{
		revertToOld();
		ihandled = true;
	}
	else if(msg.Msg==MSG_ATK)
	{

	}

	else if(msg.Msg == MSG_ATKCOLLIDE)
	{
		DmgRcv(rand() % 4 + 1);

		if(getHP() <= 0)
		{
			death();
		}
		ihandled = true;
	}

	return ihandled;
}

void Player::updatePlayerFSM()
{
	if(m_PlayerState)
	{
		m_PlayerState->Update();
	}
}

void Player::vectorUpdate(float posit)
{
	updateDelta();
	m_position.x = m_position.x + ((m_delta.x*posit) * m_dt);
	m_position.y = m_position.y + ((m_delta.y*posit) * m_dt);
	m_position.z = m_position.z + ((m_delta.z*posit) * m_dt);
}
void Player::perpVectorUpdate(float posit)
{
	m_position.x = m_position.x + ((m_tDir.x*m_magnitude.x*posit) * m_dt);
	m_position.y = m_position.y + ((m_tDir.y*m_magnitude.y*posit) * m_dt);
	m_position.z = m_position.z + ((m_tDir.z*m_magnitude.z*posit) * m_dt);
}

void Player::move(int direction, float anim_rate)
{
	switch (direction)
	{
		case P_FORWARD:
			vectorUpdate(1.0);	//Moves point along vector
		break;

		case P_BACKWARD:
			vectorUpdate(-1.0);//Moves point along vector
		break;

		case P_LEFT:
			m_VectorRotation.z -= 100.0f*m_dt;
			rotateVector();
			updateDelta();

		break;

		case P_RIGHT:
			m_VectorRotation.z += 100.0f*m_dt;
			rotateVector();
			updateDelta();

		break;
		case P_STRAFE_LEFT:
			perpVectorUpdate(-1.0);//Moves point along vector
		break;

		case P_STRAFE_RIGHT:
			perpVectorUpdate(1.0);//Moves point along vector
		break;
	}
}

void Player::PlayerInput()
{
	m_oldPosit = m_position;
	// If the W key is pressed, move forward
	if (diMgr.isKeyDown(DIK_W))
		move(Player::P_FORWARD, 0.3f);
			
	// If the S key is pressed, move backwards
	if (diMgr.isKeyDown(DIK_S))
		move(Player::P_BACKWARD, 0);

	// If the middle mouse button is pressed, close window
	if (diMgr.isButtonDown(2))
		PostQuitMessage(0);

	if (diMgr.isKeyDown(DIK_X) && diMgr.isKeyDown(DIK_LSHIFT))
		PostQuitMessage(0);
			
	// If the mouse is moved to the left, turn left
	if (diMgr.getCurMouseX() < 0)			
		move(Player::P_LEFT, 0);
			
	// If the mouse is moved to the right, turn right
	if (diMgr.getCurMouseX() > 0)
		move(Player::P_RIGHT, 0);

	// If the mouse is moved down, decrease height
	if (diMgr.getCurMouseY() < 0 )			
		m_camera->rotDown(10);
			
	// If the mouse is moved up, increase height
	if (diMgr.getCurMouseY() > 0)
		m_camera->rotUp(10);

	// If the mouse wheel is moved up, increase distance
	if (diMgr.getCurMouseWheel() > 0)
		m_camera->addDistance(-10);

	// If the mouse wheel is moved down, decrease distance
	if (diMgr.getCurMouseWheel() < 0)
		m_camera->addDistance(10);

	if (diMgr.isKeyDown(DIK_A))
		move(Player::P_STRAFE_LEFT, 0.3f);
			
	if (diMgr.isKeyDown(DIK_D))
		move(Player::P_STRAFE_RIGHT, 0);

	if(m_energy >= 10)
	{
		if (diMgr.KeyDownEvent(DIK_1))
		{
			dxAmgr.playSound(DSBuffer2);
			m_eBall = new EnergyBall();
			m_eBall->setBallPos(m_position, 7.0f);
			m_eBall->setBallRot(m_VectorRotation);
			m_release = true;
			setEnergy(10);
		}
	}

	if(m_energy >= 20)
	{
		if (diMgr.KeyDownEvent(DIK_2))
		{
			dxAmgr.playSound(DSBuffer2);
			m_bscale = 5.0f;
			m_eBall2 = new EnergyBall();
			m_eBall2->setBallPos(m_position, m_bscale);
			m_eBall2->setBallRot(m_VectorRotation);
			m_pBall = true;
			m_expand = false;
			setEnergy(20);
		}
		diMgr.checkBuffers();
	}
}

void Player::render(LPDIRECT3DDEVICE9 device)
{
	//render
	 m_Model->render(device);
	 m_DXNOVA.DXDrawText(fontRedColor);
	 m_DXNOVA2.DXDrawText(fontGreenColor);
	 m_DXNOVA3.DXDrawText(fontBlueColor);
	 m_DXNOVA4.DXDrawText(fontBlueColor);

	if(m_release)
	{
		 m_eBall->updateBall(m_dt);
	}

	if(m_pBall)
	{
		if(diMgr.ButtonDownEvent(1))
		{
			dxAmgr.playSound(DSBuffer4);
			m_expand = true;
		}
		diMgr.chckMouseBuffers();

		if(m_expand)
		{
			m_bscale += 1.0f;
			m_eBall2->setNukeScale(m_bscale);
			m_eBall2->ballStay();
		}
		m_eBall2->updateBall(m_dt);
	}
}

bool Player::nukeCreate()
{
	return m_expand;
}

bool Player::create(LPDIRECT3DDEVICE9 device, std::string modelName)
{
	m_position.x = 0.0f;
	m_position.y = 0.0f;
	m_position.z = 0.0f;

	m_VectorRotation.x = 0.0f;//hip to hip
	m_VectorRotation.y = 0.0;//Crotch to butt
	m_VectorRotation.z = 0.0f;//Head to Foot
	setOld();

	m_radius = 25;
	m_melee = 100;
	m_camera = new Camera();

	setHP(100);
	
	m_Model = new Model();
	return m_Model->loadModel(device,modelName);
}

void Player::combat1()
{
	if(diMgr.ButtonDownEvent(0))
	{
		dxAmgr.playSound(DSBuffer);
		Handler->SendMessage(0.0,0,1,MSG_ATKCOLLIDE,NULL);
	}
	diMgr.chckMouseBuffers(); 
}

void Player::combat2()
{
	if(diMgr.ButtonDownEvent(0))
	{
		dxAmgr.playSound(DSBuffer);
		Handler->SendMessage(0.0,0,2,MSG_ATKCOLLIDE,NULL);
	}
	diMgr.chckMouseBuffers(); 
}

void Player::combat3()
{
	if(diMgr.ButtonDownEvent(0))
	{
		dxAmgr.playSound(DSBuffer);
		Handler->SendMessage(0.0,0,3,MSG_ATKCOLLIDE,NULL);
	}
	diMgr.chckMouseBuffers(); 
}

void Player::combat4()
{
	if(diMgr.ButtonDownEvent(0))
	{
		dxAmgr.playSound(DSBuffer);
		Handler->SendMessage(0.0,0,4,MSG_ATKCOLLIDE,NULL);
	}
	diMgr.chckMouseBuffers();
}

bool Player::death()
{
	bool isPlayerDead = false;

	if(getHP() <= 0)
	{
		setVectorRotation(0,0,0);
		isPlayerDead = true;
	}

	return isPlayerDead;
}

void Player::chargeEnergy()
{
	if(m_ok == 1)
	{
		if(m_energy < 100)
		{
			m_energy += 5;
		}
	}
}

void Player::setOK(int timeok)
{
	m_ok = timeok;
}

void Player::loadSounds()
{
	
}

bool Player::checkSounds()
{
	if (!DSBuffer)
	{
		return false;
	}

	if (!DSBuffer2)
	{
		return false;
	}

	if (!DSBuffer3)
	{
		return false;
	}

	if (!DSBuffer4)
	{
		return false;
	}

	return true;
}

void Player::releaseSounds()
{
	if (DSBuffer)
	{
		DSBuffer->Release();
		DSBuffer = NULL;
	}

	if (DSBuffer2)
	{
		DSBuffer2->Release();
		DSBuffer2 = NULL;
	}

	if (DSBuffer3)
	{
		DSBuffer3->Release();
		DSBuffer3 = NULL;
	}

	if (DSBuffer4)
	{
		DSBuffer4->Release();
		DSBuffer4 = NULL;
	}
}

bool Player::isBallOn()
{
	return m_release;
}

bool Player::nukeOn()
{
	return m_pBall;
}

D3DXVECTOR3 Player::getEballPos()
{
	if(m_release)
	{
		return m_eBall->getBallPos();
	}
	
	else
	{
		D3DXVECTOR3 no_Ball;
		return no_Ball;
	}
}

float Player::getEballRad()
{
	if(m_release)
	{
		return m_eBall->getBallRad();
	}
	
	else
	{
		return 0;
	}
}

void Player::EraseBall()
{
	if(m_release)
	{
		dxAmgr.playSound(DSBuffer3);
		if(m_eBall != NULL)
		{
			delete m_eBall;
			m_eBall = NULL;
		}
		m_release = false;
	}
}

D3DXVECTOR3 Player::getENukePos()
{	
	if(m_pBall)
	{
		return m_eBall2->getNukePos();
	}
	
	else
	{
		D3DXVECTOR3 no_Ball;
		return no_Ball;
	}
}

float Player::getENukeRad()
{
	if(m_pBall)
	{
		return m_eBall2->getNukeRad();
	}
	
	else
	{
		return 0;
	}
}


void Player::Nuke()
{
	if(m_pBall)
	{
		if(m_eBall2 != NULL)
		{
			delete m_eBall2;
			m_eBall2 = NULL;
		}
		m_pBall = false;
	}
}